home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / gettext / intl / setlocale.c < prev    next >
Encoding:
C/C++ Source or Header  |  2010-09-19  |  30.4 KB  |  1,016 lines

  1. /* setlocale() function that respects the locale chosen by the user.
  2.    Copyright (C) 2009 Free Software Foundation, Inc.
  3.    Written by Bruno Haible <bruno@clisp.org>, 2009.
  4.  
  5.    This program is free software; you can redistribute it and/or modify it
  6.    under the terms of the GNU Library General Public License as published
  7.    by the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.    Library General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU Library General Public
  16.    License along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  18.    USA.  */
  19.  
  20. #ifdef HAVE_CONFIG_H
  21. # include <config.h>
  22. #endif
  23.  
  24. /* Override setlocale() and newlocale() so that when the default locale is
  25.    requested (locale = "") and no relevant environment variable is set, the
  26.    locale chosen by the user is used.
  27.    This matters on MacOS X 10 and Windows.
  28.    See the comments in localename.c, function gl_locale_name_default.  */
  29.  
  30. #include <locale.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33.  
  34. /* When building a DLL, we must export some functions.  Note that because
  35.    the functions are only defined for binary backward compatibility, we
  36.    don't need to use __declspec(dllimport) in any case.  */
  37. #if HAVE_VISIBILITY && BUILDING_DLL
  38. # define DLL_EXPORTED __attribute__((__visibility__("default")))
  39. #elif defined _MSC_VER && BUILDING_DLL
  40. # define DLL_EXPORTED __declspec(dllexport)
  41. #else
  42. # define DLL_EXPORTED
  43. #endif
  44.  
  45. #include "gettextP.h"
  46.  
  47. #if (defined __APPLE__ && defined __MACH__) || defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
  48.  
  49. # undef setlocale
  50. # undef newlocale
  51.  
  52. /* Return string representation of locale category CATEGORY.  */
  53. static const char *
  54. category_to_name (int category)
  55. {
  56.   const char *retval;
  57.  
  58.   switch (category)
  59.   {
  60.   case LC_COLLATE:
  61.     retval = "LC_COLLATE";
  62.     break;
  63.   case LC_CTYPE:
  64.     retval = "LC_CTYPE";
  65.     break;
  66.   case LC_MONETARY:
  67.     retval = "LC_MONETARY";
  68.     break;
  69.   case LC_NUMERIC:
  70.     retval = "LC_NUMERIC";
  71.     break;
  72.   case LC_TIME:
  73.     retval = "LC_TIME";
  74.     break;
  75.   case LC_MESSAGES:
  76.     retval = "LC_MESSAGES";
  77.     break;
  78.   default:
  79.     /* If you have a better idea for a default value let me know.  */
  80.     retval = "LC_XXX";
  81.   }
  82.  
  83.   return retval;
  84. }
  85.  
  86. # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  87.  
  88. /* The native Win32 setlocale() function expects locale names of the form
  89.    "German" or "German_Germany" or "DEU", but not "de" or "de_DE".  We need
  90.    to convert the names from the form with ISO 639 language code and ISO 3166
  91.    country code to the form with English names or with three-letter identifier.
  92.    The three-letter identifiers known by a Windows XP SP2 or SP3 are:
  93.      AFK  Afrikaans_South Africa.1252
  94.      ARA  Arabic_Saudi Arabia.1256
  95.      ARB  Arabic_Lebanon.1256
  96.      ARE  Arabic_Egypt.1256
  97.      ARG  Arabic_Algeria.1256
  98.      ARH  Arabic_Bahrain.1256
  99.      ARI  Arabic_Iraq.1256
  100.      ARJ  Arabic_Jordan.1256
  101.      ARK  Arabic_Kuwait.1256
  102.      ARL  Arabic_Libya.1256
  103.      ARM  Arabic_Morocco.1256
  104.      ARO  Arabic_Oman.1256
  105.      ARQ  Arabic_Qatar.1256
  106.      ARS  Arabic_Syria.1256
  107.      ART  Arabic_Tunisia.1256
  108.      ARU  Arabic_U.A.E..1256
  109.      ARY  Arabic_Yemen.1256
  110.      AZE  Azeri (Latin)_Azerbaijan.1254
  111.      BEL  Belarusian_Belarus.1251
  112.      BGR  Bulgarian_Bulgaria.1251
  113.      BSB  Bosnian_Bosnia and Herzegovina.1250
  114.      BSC  Bosnian (Cyrillic)_Bosnia and Herzegovina.1250  (wrong encoding!)
  115.      CAT  Catalan_Spain.1252
  116.      CHH  Chinese_Hong Kong S.A.R..950
  117.      CHI  Chinese_Singapore.936
  118.      CHS  Chinese_People's Republic of China.936
  119.      CHT  Chinese_Taiwan.950
  120.      CSY  Czech_Czech Republic.1250
  121.      CYM  Welsh_United Kingdom.1252
  122.      DAN  Danish_Denmark.1252
  123.      DEA  German_Austria.1252
  124.      DEC  German_Liechtenstein.1252
  125.      DEL  German_Luxembourg.1252
  126.      DES  German_Switzerland.1252
  127.      DEU  German_Germany.1252
  128.      ELL  Greek_Greece.1253
  129.      ENA  English_Australia.1252
  130.      ENB  English_Caribbean.1252
  131.      ENC  English_Canada.1252
  132.      ENG  English_United Kingdom.1252
  133.      ENI  English_Ireland.1252
  134.      ENJ  English_Jamaica.1252
  135.      ENL  English_Belize.1252
  136.      ENP  English_Republic of the Philippines.1252
  137.      ENS  English_South Africa.1252
  138.      ENT  English_Trinidad and Tobago.1252
  139.      ENU  English_United States.1252
  140.      ENW  English_Zimbabwe.1252
  141.      ENZ  English_New Zealand.1252
  142.      ESA  Spanish_Panama.1252
  143.      ESB  Spanish_Bolivia.1252
  144.      ESC  Spanish_Costa Rica.1252
  145.      ESD  Spanish_Dominican Republic.1252
  146.      ESE  Spanish_El Salvador.1252
  147.      ESF  Spanish_Ecuador.1252
  148.      ESG  Spanish_Guatemala.1252
  149.      ESH  Spanish_Honduras.1252
  150.      ESI  Spanish_Nicaragua.1252
  151.      ESL  Spanish_Chile.1252
  152.      ESM  Spanish_Mexico.1252
  153.      ESN  Spanish_Spain.1252
  154.      ESO  Spanish_Colombia.1252
  155.      ESP  Spanish_Spain.1252
  156.      ESR  Spanish_Peru.1252
  157.      ESS  Spanish_Argentina.1252
  158.      ESU  Spanish_Puerto Rico.1252
  159.      ESV  Spanish_Venezuela.1252
  160.      ESY  Spanish_Uruguay.1252
  161.      ESZ  Spanish_Paraguay.1252
  162.      ETI  Estonian_Estonia.1257
  163.      EUQ  Basque_Spain.1252
  164.      FAR  Farsi_Iran.1256
  165.      FIN  Finnish_Finland.1252
  166.      FOS  Faroese_Faroe Islands.1252
  167.      FPO  Filipino_Philippines.1252
  168.      FRA  French_France.1252
  169.      FRB  French_Belgium.1252
  170.      FRC  French_Canada.1252
  171.      FRL  French_Luxembourg.1252
  172.      FRM  French_Principality of Monaco.1252
  173.      FRS  French_Switzerland.1252
  174.      FYN  Frisian_Netherlands.1252
  175.      GLC  Galician_Spain.1252
  176.      HEB  Hebrew_Israel.1255
  177.      HRB  Croatian_Bosnia and Herzegovina.1250
  178.      HRV  Croatian_Croatia.1250
  179.      HUN  Hungarian_Hungary.1250
  180.      IND  Indonesian_Indonesia.1252
  181.      IRE  Irish_Ireland.1252
  182.      ISL  Icelandic_Iceland.1252
  183.      ITA  Italian_Italy.1252
  184.      ITS  Italian_Switzerland.1252
  185.      IUK  Inuktitut (Latin)_Canada.1252
  186.      JPN  Japanese_Japan.932
  187.      KKZ  Kazakh_Kazakhstan.1251
  188.      KOR  Korean_Korea.949
  189.      KYR  Kyrgyz_Kyrgyzstan.1251
  190.      LBX  Luxembourgish_Luxembourg.1252
  191.      LTH  Lithuanian_Lithuania.1257
  192.      LVI  Latvian_Latvia.1257
  193.      MKI  FYRO Macedonian_Former Yugoslav Republic of Macedonia.1251
  194.      MON  Mongolian_Mongolia.1251
  195.      MPD  Mapudungun_Chile.1252
  196.      MSB  Malay_Brunei Darussalam.1252
  197.      MSL  Malay_Malaysia.1252
  198.      MWK  Mohawk_Canada.1252
  199.      NLB  Dutch_Belgium.1252
  200.      NLD  Dutch_Netherlands.1252
  201.      NON  Norwegian-Nynorsk_Norway.1252
  202.      NOR  Norwegian (Bokm├Ñl)_Norway.1252
  203.      NSO  Northern Sotho_South Africa.1252
  204.      PLK  Polish_Poland.1250
  205.      PTB  Portuguese_Brazil.1252
  206.      PTG  Portuguese_Portugal.1252
  207.      QUB  Quechua_Bolivia.1252
  208.      QUE  Quechua_Ecuador.1252
  209.      QUP  Quechua_Peru.1252
  210.      RMC  Romansh_Switzerland.1252
  211.      ROM  Romanian_Romania.1250
  212.      RUS  Russian_Russia.1251
  213.      SKY  Slovak_Slovakia.1250
  214.      SLV  Slovenian_Slovenia.1250
  215.      SMA  Sami (Southern)_Norway.1252
  216.      SMB  Sami (Southern)_Sweden.1252
  217.      SME  Sami (Northern)_Norway.1252
  218.      SMF  Sami (Northern)_Sweden.1252
  219.      SMG  Sami (Northern)_Finland.1252
  220.      SMJ  Sami (Lule)_Norway.1252
  221.      SMK  Sami (Lule)_Sweden.1252
  222.      SMN  Sami (Inari)_Finland.1252
  223.      SMS  Sami (Skolt)_Finland.1252
  224.      SQI  Albanian_Albania.1250
  225.      SRB  Serbian (Cyrillic)_Serbia and Montenegro.1251
  226.      SRL  Serbian (Latin)_Serbia and Montenegro.1250
  227.      SRN  Serbian (Cyrillic)_Bosnia and Herzegovina.1251
  228.      SRS  Serbian (Latin)_Bosnia and Herzegovina.1250
  229.      SVE  Swedish_Sweden.1252
  230.      SVF  Swedish_Finland.1252
  231.      SWK  Swahili_Kenya.1252
  232.      THA  Thai_Thailand.874
  233.      TRK  Turkish_Turkey.1254
  234.      TSN  Tswana_South Africa.1252
  235.      TTT  Tatar_Russia.1251
  236.      UKR  Ukrainian_Ukraine.1251
  237.      URD  Urdu_Islamic Republic of Pakistan.1256
  238.      USA  English_United States.1252
  239.      UZB  Uzbek (Latin)_Uzbekistan.1254
  240.      VIT  Vietnamese_Viet Nam.1258
  241.      XHO  Xhosa_South Africa.1252
  242.      ZHH  Chinese_Hong Kong S.A.R..950
  243.      ZHI  Chinese_Singapore.936
  244.      ZHM  Chinese_Macau S.A.R..950
  245.      ZUL  Zulu_South Africa.1252
  246.  */
  247.  
  248. /* Table from ISO 639 language code, optionally with country or script suffix,
  249.    to English name.
  250.    Keep in sync with the gl_locale_name_from_win32_LANGID function in
  251.    localename.c!  */
  252. struct table_entry
  253. {
  254.   const char *code;
  255.   const char *english;
  256. };
  257. static const struct table_entry language_table[] =
  258.   {
  259.     { "af", "Afrikaans" },
  260.     { "am", "Amharic" },
  261.     { "ar", "Arabic" },
  262.     { "arn", "Mapudungun" },
  263.     { "as", "Assamese" },
  264.     { "az@cyrillic", "Azeri (Cyrillic)" },
  265.     { "az@latin", "Azeri (Latin)" },
  266.     { "ba", "Bashkir" },
  267.     { "be", "Belarusian" },
  268.     { "ber", "Tamazight" },
  269.     { "ber@arabic", "Tamazight (Arabic)" },
  270.     { "ber@latin", "Tamazight (Latin)" },
  271.     { "bg", "Bulgarian" },
  272.     { "bin", "Edo" },
  273.     { "bn", "Bengali" },
  274.     { "bn_BD", "Bengali (Bangladesh)" },
  275.     { "bn_IN", "Bengali (India)" },
  276.     { "bnt", "Sutu" },
  277.     { "bo", "Tibetan" },
  278.     { "br", "Breton" },
  279.     { "bs", "BSB" }, /* "Bosnian (Latin)" */
  280.     { "bs@cyrillic", "BSC" }, /* Bosnian (Cyrillic) */
  281.     { "ca", "Catalan" },
  282.     { "chr", "Cherokee" },
  283.     { "co", "Corsican" },
  284.     { "cpe", "Hawaiian" },
  285.     { "cs", "Czech" },
  286.     { "cy", "Welsh" },
  287.     { "da", "Danish" },
  288.     { "de", "German" },
  289.     { "dsb", "Lower Sorbian" },
  290.     { "dv", "Divehi" },
  291.     { "el", "Greek" },
  292.     { "en", "English" },
  293.     { "es", "Spanish" },
  294.     { "et", "Estonian" },
  295.     { "eu", "Basque" },
  296.     { "fa", "Farsi" },
  297.     { "ff", "Fulfulde" },
  298.     { "fi", "Finnish" },
  299.     { "fo", "Faroese" }, /* "Faeroese" does not work */
  300.     { "fr", "French" },
  301.     { "fy", "Frisian" },
  302.     { "ga", "IRE" }, /* Gaelic (Ireland) */
  303.     { "gd", "Gaelic (Scotland)" },
  304.     { "gd", "Scottish Gaelic" },
  305.     { "gl", "Galician" },
  306.     { "gn", "Guarani" },
  307.     { "gsw", "Alsatian" },
  308.     { "gu", "Gujarati" },
  309.     { "ha", "Hausa" },
  310.     { "he", "Hebrew" },
  311.     { "hi", "Hindi" },
  312.     { "hr", "Croatian" },
  313.     { "hsb", "Upper Sorbian" },
  314.     { "hu", "Hungarian" },
  315.     { "hy", "Armenian" },
  316.     { "id", "Indonesian" },
  317.     { "ig", "Igbo" },
  318.     { "ii", "Yi" },
  319.     { "is", "Icelandic" },
  320.     { "it", "Italian" },
  321.     { "iu", "IUK" }, /* Inuktitut */
  322.     { "ja", "Japanese" },
  323.     { "ka", "Georgian" },
  324.     { "kk", "Kazakh" },
  325.     { "kl", "Greenlandic" },
  326.     { "km", "Cambodian" },
  327.     { "km", "Khmer" },
  328.     { "kn", "Kannada" },
  329.     { "ko", "Korean" },
  330.     { "kok", "Konkani" },
  331.     { "kr", "Kanuri" },
  332.     { "ks", "Kashmiri" },
  333.     { "ks_IN", "Kashmiri_India" },
  334.     { "ks_PK", "Kashmiri (Arabic)_Pakistan" },
  335.     { "ky", "Kyrgyz" },
  336.     { "la", "Latin" },
  337.     { "lb", "Luxembourgish" },
  338.     { "lo", "Lao" },
  339.     { "lt", "Lithuanian" },
  340.     { "lv", "Latvian" },
  341.     { "mi", "Maori" },
  342.     { "mk", "FYRO Macedonian" },
  343.     { "mk", "Macedonian" },
  344.     { "ml", "Malayalam" },
  345.     { "mn", "Mongolian" },
  346.     { "mni", "Manipuri" },
  347.     { "moh", "Mohawk" },
  348.     { "mr", "Marathi" },
  349.     { "ms", "Malay" },
  350.     { "mt", "Maltese" },
  351.     { "my", "Burmese" },
  352.     { "nb", "NOR" }, /* Norwegian Bokm├Ñl */
  353.     { "ne", "Nepali" },
  354.     { "nic", "Ibibio" },
  355.     { "nl", "Dutch" },
  356.     { "nn", "NON" }, /* Norwegian Nynorsk */
  357.     { "no", "Norwegian" },
  358.     { "nso", "Northern Sotho" },
  359.     { "nso", "Sepedi" },
  360.     { "oc", "Occitan" },
  361.     { "om", "Oromo" },
  362.     { "or", "Oriya" },
  363.     { "pa", "Punjabi" },
  364.     { "pap", "Papiamentu" },
  365.     { "pl", "Polish" },
  366.     { "prs", "Dari" },
  367.     { "ps", "Pashto" },
  368.     { "pt", "Portuguese" },
  369.     { "qu", "Quechua" },
  370.     { "qut", "K'iche'" },
  371.     { "rm", "Romansh" },
  372.     { "ro", "Romanian" },
  373.     { "ru", "Russian" },
  374.     { "rw", "Kinyarwanda" },
  375.     { "sa", "Sanskrit" },
  376.     { "sah", "Yakut" },
  377.     { "sd", "Sindhi" },
  378.     { "se", "Sami (Northern)" },
  379.     { "se", "Northern Sami" },
  380.     { "si", "Sinhalese" },
  381.     { "sk", "Slovak" },
  382.     { "sl", "Slovenian" },
  383.     { "sma", "Sami (Southern)" },
  384.     { "sma", "Southern Sami" },
  385.     { "smj", "Sami (Lule)" },
  386.     { "smj", "Lule Sami" },
  387.     { "smn", "Sami (Inari)" },
  388.     { "smn", "Inari Sami" },
  389.     { "sms", "Sami (Skolt)" },
  390.     { "sms", "Skolt Sami" },
  391.     { "so", "Somali" },
  392.     { "sq", "Albanian" },
  393.     { "sr", "Serbian (Latin)" },
  394.     { "sr@cyrillic", "SRB" }, /* Serbian (Cyrillic) */
  395.     { "sw", "Swahili" },
  396.     { "syr", "Syriac" },
  397.     { "ta", "Tamil" },
  398.     { "te", "Telugu" },
  399.     { "tg", "Tajik" },
  400.     { "th", "Thai" },
  401.     { "ti", "Tigrinya" },
  402.     { "tk", "Turkmen" },
  403.     { "tl", "Filipino" },
  404.     { "tn", "Tswana" },
  405.     { "tr", "Turkish" },
  406.     { "ts", "Tsonga" },
  407.     { "tt", "Tatar" },
  408.     { "ug", "Uighur" },
  409.     { "uk", "Ukrainian" },
  410.     { "ur", "Urdu" },
  411.     { "uz", "Uzbek" },
  412.     { "uz", "Uzbek (Latin)" },
  413.     { "uz@cyrillic", "Uzbek (Cyrillic)" },
  414.     { "ve", "Venda" },
  415.     { "vi", "Vietnamese" },
  416.     { "wen", "Sorbian" },
  417.     { "wo", "Wolof" },
  418.     { "xh", "Xhosa" },
  419.     { "yi", "Yiddish" },
  420.     { "yo", "Yoruba" },
  421.     { "zh", "Chinese" },
  422.     { "zu", "Zulu" }
  423.   };
  424.  
  425. /* Table from ISO 3166 country code to English name.
  426.    Keep in sync with the gl_locale_name_from_win32_LANGID function in
  427.    localename.c!  */
  428. static const struct table_entry country_table[] =
  429.   {
  430.     { "AE", "U.A.E." },
  431.     { "AF", "Afghanistan" },
  432.     { "AL", "Albania" },
  433.     { "AM", "Armenia" },
  434.     { "AN", "Netherlands Antilles" },
  435.     { "AR", "Argentina" },
  436.     { "AT", "Austria" },
  437.     { "AU", "Australia" },
  438.     { "AZ", "Azerbaijan" },
  439.     { "BA", "Bosnia and Herzegovina" },
  440.     { "BD", "Bangladesh" },
  441.     { "BE", "Belgium" },
  442.     { "BG", "Bulgaria" },
  443.     { "BH", "Bahrain" },
  444.     { "BN", "Brunei Darussalam" },
  445.     { "BO", "Bolivia" },
  446.     { "BR", "Brazil" },
  447.     { "BT", "Bhutan" },
  448.     { "BY", "Belarus" },
  449.     { "BZ", "Belize" },
  450.     { "CA", "Canada" },
  451.     { "CG", "Congo" },
  452.     { "CH", "Switzerland" },
  453.     { "CI", "Cote d'Ivoire" },
  454.     { "CL", "Chile" },
  455.     { "CM", "Cameroon" },
  456.     { "CN", "People's Republic of China" },
  457.     { "CO", "Colombia" },
  458.     { "CR", "Costa Rica" },
  459.     { "CS", "Serbia and Montenegro" },
  460.     { "CZ", "Czech Republic" },
  461.     { "DE", "Germany" },
  462.     { "DK", "Denmark" },
  463.     { "DO", "Dominican Republic" },
  464.     { "DZ", "Algeria" },
  465.     { "EC", "Ecuador" },
  466.     { "EE", "Estonia" },
  467.     { "EG", "Egypt" },
  468.     { "ER", "Eritrea" },
  469.     { "ES", "Spain" },
  470.     { "ET", "Ethiopia" },
  471.     { "FI", "Finland" },
  472.     { "FO", "Faroe Islands" },
  473.     { "FR", "France" },
  474.     { "GB", "United Kingdom" },
  475.     { "GD", "Caribbean" },
  476.     { "GE", "Georgia" },
  477.     { "GL", "Greenland" },
  478.     { "GR", "Greece" },
  479.     { "GT", "Guatemala" },
  480.     { "HK", "Hong Kong" },
  481.     { "HK", "Hong Kong S.A.R." },
  482.     { "HN", "Honduras" },
  483.     { "HR", "Croatia" },
  484.     { "HT", "Haiti" },
  485.     { "HU", "Hungary" },
  486.     { "ID", "Indonesia" },
  487.     { "IE", "Ireland" },
  488.     { "IL", "Israel" },
  489.     { "IN", "India" },
  490.     { "IQ", "Iraq" },
  491.     { "IR", "Iran" },
  492.     { "IS", "Iceland" },
  493.     { "IT", "Italy" },
  494.     { "JM", "Jamaica" },
  495.     { "JO", "Jordan" },
  496.     { "JP", "Japan" },
  497.     { "KE", "Kenya" },
  498.     { "KG", "Kyrgyzstan" },
  499.     { "KH", "Cambodia" },
  500.     { "KR", "South Korea" },
  501.     { "KW", "Kuwait" },
  502.     { "KZ", "Kazakhstan" },
  503.     { "LA", "Laos" },
  504.     { "LB", "Lebanon" },
  505.     { "LI", "Liechtenstein" },
  506.     { "LK", "Sri Lanka" },
  507.     { "LT", "Lithuania" },
  508.     { "LU", "Luxembourg" },
  509.     { "LV", "Latvia" },
  510.     { "LY", "Libya" },
  511.     { "MA", "Morocco" },
  512.     { "MC", "Principality of Monaco" },
  513.     { "MD", "Moldava" },
  514.     { "MD", "Moldova" },
  515.     { "ME", "Montenegro" },
  516.     { "MK", "Former Yugoslav Republic of Macedonia" },
  517.     { "ML", "Mali" },
  518.     { "MM", "Myanmar" },
  519.     { "MN", "Mongolia" },
  520.     { "MO", "Macau S.A.R." },
  521.     { "MT", "Malta" },
  522.     { "MV", "Maldives" },
  523.     { "MX", "Mexico" },
  524.     { "MY", "Malaysia" },
  525.     { "NG", "Nigeria" },
  526.     { "NI", "Nicaragua" },
  527.     { "NL", "Netherlands" },
  528.     { "NO", "Norway" },
  529.     { "NP", "Nepal" },
  530.     { "NZ", "New Zealand" },
  531.     { "OM", "Oman" },
  532.     { "PA", "Panama" },
  533.     { "PE", "Peru" },
  534.     { "PH", "Philippines" },
  535.     { "PK", "Islamic Republic of Pakistan" },
  536.     { "PL", "Poland" },
  537.     { "PR", "Puerto Rico" },
  538.     { "PT", "Portugal" },
  539.     { "PY", "Paraguay" },
  540.     { "QA", "Qatar" },
  541.     { "RE", "Reunion" },
  542.     { "RO", "Romania" },
  543.     { "RS", "Serbia" },
  544.     { "RU", "Russia" },
  545.     { "RW", "Rwanda" },
  546.     { "SA", "Saudi Arabia" },
  547.     { "SE", "Sweden" },
  548.     { "SG", "Singapore" },
  549.     { "SI", "Slovenia" },
  550.     { "SK", "Slovak" },
  551.     { "SN", "Senegal" },
  552.     { "SO", "Somalia" },
  553.     { "SR", "Suriname" },
  554.     { "SV", "El Salvador" },
  555.     { "SY", "Syria" },
  556.     { "TH", "Thailand" },
  557.     { "TJ", "Tajikistan" },
  558.     { "TM", "Turkmenistan" },
  559.     { "TN", "Tunisia" },
  560.     { "TR", "Turkey" },
  561.     { "TT", "Trinidad and Tobago" },
  562.     { "TW", "Taiwan" },
  563.     { "TZ", "Tanzania" },
  564.     { "UA", "Ukraine" },
  565.     { "US", "United States" },
  566.     { "UY", "Uruguay" },
  567.     { "VA", "Vatican" },
  568.     { "VE", "Venezuela" },
  569.     { "VN", "Viet Nam" },
  570.     { "YE", "Yemen" },
  571.     { "ZA", "South Africa" },
  572.     { "ZW", "Zimbabwe" }
  573.   };
  574.  
  575. /* Given a string STRING, find the set of indices i such that TABLE[i].code is
  576.    the given STRING.  It is a range [lo,hi-1].  */
  577. typedef struct { size_t lo; size_t hi; } range_t;
  578. static void
  579. search (const struct table_entry *table, size_t table_size, const char *string,
  580.         range_t *result)
  581. {
  582.   /* The table is sorted.  Perform a binary search.  */
  583.   size_t hi = table_size;
  584.   size_t lo = 0;
  585.   while (lo < hi)
  586.     {
  587.       /* Invariant:
  588.          for i < lo, strcmp (table[i].code, string) < 0,
  589.          for i >= hi, strcmp (table[i].code, string) > 0.  */
  590.       size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
  591.       int cmp = strcmp (table[mid].code, string);
  592.       if (cmp < 0)
  593.         lo = mid + 1;
  594.       else if (cmp > 0)
  595.         hi = mid;
  596.       else
  597.         {
  598.           /* Found an i with
  599.                strcmp (language_table[i].code, string) == 0.
  600.              Find the entire interval of such i.  */
  601.           {
  602.             size_t i;
  603.  
  604.             for (i = mid; i > lo; )
  605.               {
  606.                 i--;
  607.                 if (strcmp (table[i].code, string) < 0)
  608.                   {
  609.                     lo = i + 1;
  610.                     break;
  611.                   }
  612.               }
  613.           }
  614.           {
  615.             size_t i;
  616.  
  617.             for (i = mid; i < hi; i++)
  618.               {
  619.                 if (strcmp (table[i].code, string) > 0)
  620.                   {
  621.                     hi = i;
  622.                     break;
  623.                   }
  624.               }
  625.           }
  626.           /* The set of i with
  627.                strcmp (language_table[i].code, string) == 0
  628.              is the interval [lo, hi-1].  */
  629.           break;
  630.         }
  631.     }
  632.   result->lo = lo;
  633.   result->hi = hi;
  634. }
  635.  
  636. /* Like setlocale, but accept also locale names in the form ll or ll_CC,
  637.    where ll is an ISO 639 language code and CC is an ISO 3166 country code.  */
  638. static char *
  639. setlocale_unixlike (int category, const char *locale)
  640. {
  641.   char *result;
  642.   char llCC_buf[64];
  643.   char ll_buf[64];
  644.   char CC_buf[64];
  645.  
  646.   /* First, try setlocale with the original argument unchanged.  */
  647.   result = setlocale (category, locale);
  648.   if (result != NULL)
  649.     return result;
  650.  
  651.   /* Otherwise, assume the argument is in the form
  652.        language[_territory][.codeset][@modifier]
  653.      and try to map it using the tables.  */
  654.   if (strlen (locale) < sizeof (llCC_buf))
  655.     {
  656.       /* Second try: Remove the codeset part.  */
  657.       {
  658.         const char *p = locale;
  659.         char *q = llCC_buf;
  660.  
  661.         /* Copy the part before the dot.  */
  662.         for (; *p != '\0' && *p != '.'; p++, q++)
  663.           *q = *p;
  664.         if (*p == '.')
  665.           /* Skip the part up to the '@', if any.  */
  666.           for (; *p != '\0' && *p != '@'; p++)
  667.             ;
  668.         /* Copy the part starting with '@', if any.  */
  669.         for (; *p != '\0'; p++, q++)
  670.           *q = *p;
  671.         *q = '\0';
  672.       }
  673.       /* llCC_buf now contains
  674.            language[_territory][@modifier]
  675.        */
  676.       if (strcmp (llCC_buf, locale) != 0)
  677.         {
  678.           result = setlocale (category, llCC_buf);
  679.           if (result != NULL)
  680.             return result;
  681.         }
  682.       /* Look it up in language_table.  */
  683.       {
  684.         range_t range;
  685.         size_t i;
  686.  
  687.         search (language_table,
  688.                 sizeof (language_table) / sizeof (language_table[0]),
  689.                 llCC_buf,
  690.                 &range);
  691.  
  692.         for (i = range.lo; i < range.hi; i++)
  693.           {
  694.             /* Try the replacement in language_table[i].  */
  695.             result = setlocale (category, language_table[i].english);
  696.             if (result != NULL)
  697.               return result;
  698.           }
  699.       }
  700.       /* Split language[_territory][@modifier]
  701.          into  ll_buf = language[@modifier]
  702.          and   CC_buf = territory
  703.        */
  704.       {
  705.         const char *underscore = strchr (llCC_buf, '_');
  706.         if (underscore != NULL)
  707.           {
  708.             const char *territory_start = underscore + 1;
  709.             const char *territory_end = strchr (territory_start, '@');
  710.             if (territory_end == NULL)
  711.               territory_end = territory_start + strlen (territory_start);
  712.  
  713.             memcpy (ll_buf, llCC_buf, underscore - llCC_buf);
  714.             strcpy (ll_buf + (underscore - llCC_buf), territory_end);
  715.  
  716.             memcpy (CC_buf, territory_start, territory_end - territory_start);
  717.             CC_buf[territory_end - territory_start] = '\0';
  718.  
  719.             {
  720.               /* Look up ll_buf in language_table
  721.                  and CC_buf in country_table.  */
  722.               range_t language_range;
  723.  
  724.               search (language_table,
  725.                       sizeof (language_table) / sizeof (language_table[0]),
  726.                       ll_buf,
  727.                       &language_range);
  728.               if (language_range.lo < language_range.hi)
  729.                 {
  730.                   range_t country_range;
  731.  
  732.                   search (country_table,
  733.                           sizeof (country_table) / sizeof (country_table[0]),
  734.                           CC_buf,
  735.                           &country_range);
  736.                   if (country_range.lo < country_range.hi)
  737.                     {
  738.                       size_t i;
  739.                       size_t j;
  740.  
  741.                       for (i = language_range.lo; i < language_range.hi; i++)
  742.                         for (j = country_range.lo; j < country_range.hi; j++)
  743.                           {
  744.                             /* Concatenate the replacements.  */
  745.                             const char *part1 = language_table[i].english;
  746.                             size_t part1_len = strlen (part1);
  747.                             const char *part2 = country_table[j].english;
  748.                             size_t part2_len = strlen (part2) + 1;
  749.                             char buf[64+64];
  750.  
  751.                             if (!(part1_len + 1 + part2_len <= sizeof (buf)))
  752.                               abort ();
  753.                             memcpy (buf, part1, part1_len);
  754.                             buf[part1_len] = '_';
  755.                             memcpy (buf + part1_len + 1, part2, part2_len);
  756.  
  757.                             /* Try the concatenated replacements.  */
  758.                             result = setlocale (category, buf);
  759.                             if (result != NULL)
  760.                               return result;
  761.                           }
  762.                     }
  763.  
  764.                   /* Try omitting the country entirely.  This may set a locale
  765.                      corresponding to the wrong country, but is better than
  766.                      failing entirely.  */
  767.                   {
  768.                     size_t i;
  769.  
  770.                     for (i = language_range.lo; i < language_range.hi; i++)
  771.                       {
  772.                         /* Try only the language replacement.  */
  773.                         result =
  774.                           setlocale (category, language_table[i].english);
  775.                         if (result != NULL)
  776.                           return result;
  777.                       }
  778.                   }
  779.                 }
  780.             }
  781.           }
  782.       }
  783.     }
  784.  
  785.   /* Failed.  */
  786.   return NULL;
  787. }
  788.  
  789. # else
  790. #  define setlocale_unixlike setlocale
  791. # endif
  792.  
  793. # if LC_MESSAGES == 1729
  794.  
  795. /* The system does not store an LC_MESSAGES locale category.  Do it here.  */
  796. static char lc_messages_name[64] = "C";
  797.  
  798. /* Like setlocale, but support also LC_MESSAGES.  */
  799. static char *
  800. setlocale_single (int category, const char *locale)
  801. {
  802.   if (category == LC_MESSAGES)
  803.     {
  804.       if (locale != NULL)
  805.         {
  806.           lc_messages_name[sizeof (lc_messages_name) - 1] = '\0';
  807.           strncpy (lc_messages_name, locale, sizeof (lc_messages_name) - 1);
  808.         }
  809.       return lc_messages_name;
  810.     }
  811.   else
  812.     return setlocale_unixlike (category, locale);
  813. }
  814.  
  815. # else
  816. #  define setlocale_single setlocale_unixlike
  817. # endif
  818.  
  819. DLL_EXPORTED
  820. char *
  821. libintl_setlocale (int category, const char *locale)
  822. {
  823.   if (locale != NULL && locale[0] == '\0')
  824.     {
  825.       /* A request to the set the current locale to the default locale.  */
  826.       if (category == LC_ALL)
  827.         {
  828.           /* Set LC_CTYPE first.  Then the other categories.  */
  829.           static int const categories[] =
  830.             {
  831.               LC_NUMERIC,
  832.               LC_TIME,
  833.               LC_COLLATE,
  834.               LC_MONETARY,
  835.               LC_MESSAGES
  836.             };
  837.           char *saved_locale;
  838.           const char *base_name;
  839.           unsigned int i;
  840.  
  841.           /* Back up the old locale, in case one of the steps fails.  */
  842.           saved_locale = setlocale (LC_ALL, NULL);
  843.           if (saved_locale == NULL)
  844.             return NULL;
  845.           saved_locale = strdup (saved_locale);
  846.           if (saved_locale == NULL)
  847.             return NULL;
  848.  
  849.           /* Set LC_CTYPE category.  Set all other categories (except possibly
  850.              LC_MESSAGES) to the same value in the same call; this is likely to
  851.              save calls.  */
  852.           base_name =
  853.             gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE));
  854.           if (base_name == NULL)
  855.             base_name = gl_locale_name_default ();
  856.  
  857.           if (setlocale_unixlike (LC_ALL, base_name) == NULL)
  858.             goto fail;
  859.  
  860.           for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++)
  861.             {
  862.               int cat = categories[i];
  863.               const char *name;
  864.  
  865.               name = gl_locale_name_environ (cat, category_to_name (cat));
  866.               if (name == NULL)
  867.                 name = gl_locale_name_default ();
  868.  
  869.               /* If name is the same as base_name, it has already been set
  870.                  through the setlocale call before the loop.  */
  871.               if (strcmp (name, base_name) != 0
  872. # if LC_MESSAGES == 1729
  873.                   || cat == LC_MESSAGES
  874. # endif
  875.                  )
  876.                 if (setlocale_single (cat, name) == NULL)
  877.                   goto fail;
  878.             }
  879.  
  880.           /* All steps were successful.  */
  881.           free (saved_locale);
  882.           return setlocale (LC_ALL, NULL);
  883.  
  884.         fail:
  885.           if (saved_locale[0] != '\0') /* don't risk an endless recursion */
  886.             setlocale (LC_ALL, saved_locale);
  887.           free (saved_locale);
  888.           return NULL;
  889.         }
  890.       else
  891.         {
  892.           const char *name =
  893.             gl_locale_name_environ (category, category_to_name (category));
  894.           if (name == NULL)
  895.             name = gl_locale_name_default ();
  896.  
  897.           return setlocale_single (category, name);
  898.         }
  899.     }
  900.   else
  901.     return setlocale_single (category, locale);
  902. }
  903.  
  904. # if HAVE_NEWLOCALE
  905.  
  906. DLL_EXPORTED
  907. locale_t
  908. libintl_newlocale (int category_mask, const char *locale, locale_t base)
  909. {
  910.   if (category_mask != 0 && locale != NULL && locale[0] == '\0')
  911.     {
  912.       /* A request to construct a locale_t object that refers to the default
  913.          locale.  */
  914.  
  915.       /* Set LC_CTYPE first.  Then the other categories.  */
  916.       static struct { int cat; int mask; } const categories[] =
  917.         {
  918.           { LC_CTYPE,    LC_CTYPE_MASK },
  919.           { LC_NUMERIC,  LC_NUMERIC_MASK },
  920.           { LC_TIME,     LC_TIME_MASK },
  921.           { LC_COLLATE,  LC_COLLATE_MASK },
  922.           { LC_MONETARY, LC_MONETARY_MASK },
  923.           { LC_MESSAGES, LC_MESSAGES_MASK }
  924.         };
  925.  
  926.       locale_t orig_base = base;
  927.  
  928.       if ((LC_ALL_MASK & ~category_mask) == 0)
  929.         {
  930.           const char *base_name;
  931.           unsigned int i;
  932.  
  933.           /* Set LC_CTYPE category.  Set all other categories (except possibly
  934.              LC_MESSAGES) to the same value in the same call; this is likely to
  935.              save calls.  */
  936.           base_name =
  937.             gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE));
  938.           if (base_name == NULL)
  939.             base_name = gl_locale_name_default ();
  940.  
  941.           base = newlocale (LC_ALL_MASK, base_name, base);
  942.           if (base == NULL)
  943.             return NULL;
  944.  
  945.           for (i = 1; i < sizeof (categories) / sizeof (categories[0]); i++)
  946.             {
  947.               int category = categories[i].cat;
  948.               int category_mask = categories[i].mask;
  949.               const char *name;
  950.  
  951.               name =
  952.                 gl_locale_name_environ (category, category_to_name (category));
  953.               if (name == NULL)
  954.                 name = gl_locale_name_default ();
  955.  
  956.               /* If name is the same as base_name, it has already been set
  957.                  through the setlocale call before the loop.  */
  958.               if (strcmp (name, base_name) != 0)
  959.                 {
  960.                   locale_t copy = newlocale (category_mask, name, base);
  961.                   if (copy == NULL)
  962.                     goto fail;
  963.                   /* No need to call freelocale (base) if copy != base; the
  964.                      newlocale function already takes care of doing it.  */
  965.                   base = copy;
  966.                 }
  967.             }
  968.         }
  969.       else
  970.         {
  971.           unsigned int i;
  972.  
  973.           for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++)
  974.             {
  975.               int cat_mask = categories[i].mask;
  976.  
  977.               if ((category_mask & cat_mask) != 0)
  978.                 {
  979.                   int cat = categories[i].cat;
  980.                   const char *name;
  981.                   locale_t copy;
  982.  
  983.                   name = gl_locale_name_environ (cat, category_to_name (cat));
  984.                   if (name == NULL)
  985.                     name = gl_locale_name_default ();
  986.  
  987.                   copy = newlocale (cat_mask, name, base);
  988.                   if (copy == NULL)
  989.                     goto fail;
  990.                   /* No need to call freelocale (base) if copy != base; the
  991.                      newlocale function already takes care of doing it.  */
  992.                   base = copy;
  993.                 }
  994.             }
  995.         }
  996.  
  997.       /* All steps were successful.  */
  998.       return base;
  999.  
  1000.     fail:
  1001.       if (base != NULL && orig_base == NULL)
  1002.         {
  1003.           int saved_errno = errno;
  1004.           freelocale (base);
  1005.           errno = saved_errno;
  1006.         }
  1007.       return NULL;
  1008.     }
  1009.   else
  1010.     return newlocale (category_mask, locale, base);
  1011. }
  1012.  
  1013. # endif
  1014.  
  1015. #endif
  1016.